<template>
    <PopoverModal
        v-model:visible="visible"
        :placement="placement"
        @ok="onOk"
        @cancel="onCancel"
    >
        <template #content>
            <div style="width: 450px">
                <a-form ref="formRef" layout="vertical" :model="formData">
                    <a-form-item
                        label="元素类型"
                        required
                        name="type"
                        :rules="rules"
                        :validate-first="true"
                    >
                        <ArrayTypeSelect
                            v-model:value="formData.type"
                            :data="formData"
                            @changeFormData="TypeChange"
                        />
                    </a-form-item>
                    <ScaleItem
                        v-if="showDouble"
                        v-model:value="formData.scale"
                    />
                    <StringItem
                        v-else-if="showString"
                        v-model:value="formData.expands.maxLength"
                    />
                    <BooleanItem
                        v-else-if="showBoolean"
                        v-model:value="formData.boolean"
                        name="boolean"
                    />
                    <DateItem
                        v-else-if="showDate"
                        v-model:value="formData.format"
                    />
                    <EnumItem
                        ref="enumTableRef"
                        v-else-if="showEnum"
                        v-model:value="formData.enum.elements"
                    />
                    <a-form-item
                        v-else-if="showArray"
                        label="子元素类型"
                        required
                        :name="['elementType', 'type']"
                        :rules="[
                            { required: true, message: '请选择子元素类型' },
                        ]"
                    >
                        <TypeSelect
                            v-model:value="formData.elementType"
                            :filter="['array', 'object']"
                        />
                    </a-form-item>
                </a-form>
            </div>
        </template>
        <slot>
            <a-button type="link" :disabled="disabled" style="padding: 0">
                <template #icon>
                    <AIcon
                        type="EditOutlined"
                        :class="{ 'table-form-required-aicon': !value.type }"
                    />
                </template>
            </a-button>
        </slot>
    </PopoverModal>
</template>

<script setup name="MetadataArray">
import { PopoverModal, TypeSelect } from '../index';
import ArrayTypeSelect from './ArrayTypeSelect.vue';
import ScaleItem from '../Double/ScaleItem.vue';
import StringItem from '../String/Item.vue';
import BooleanItem from '../Boolean/Item.vue';
import DateItem from '../Date/Item.vue';
import EnumItem from '../Enum/Item.vue';
import { cloneDeep, pick } from 'lodash-es';
import { Form } from 'ant-design-vue';

const emit = defineEmits(['update:value', 'cancel', 'confirm']);

const props = defineProps({
    value: {
        type: Object,
        default: () => ({}),
    },
    unitOptions: {
        type: [Array, Function],
        default: () => [],
    },
    placement: {
        type: String,
        default: 'top',
    },
    disabled: {
        type: Boolean,
        default: false,
    },
});

const formItemContext = Form.useInjectFormItemContext();

const formRef = ref();
const enumTableRef = ref();
const visible = ref(false);
const formData = ref({
    type: props.value?.type,
    scale: props.value?.scale,
    expands: {
        maxLength: props.value?.maxLength || props.value?.expands?.maxLength,
    },
    boolean: {
        trueText: props.value?.trueText || '是',
        trueValue: props.value?.trueValue || 'true',
        falseText: props.value?.falseText || '否',
        falseValue: props.value?.falseValue || 'false',
    },
    format: props.value?.format,
    enum: {
        multiple: props.value?.multiple,
        elements: cloneDeep(props.value?.elements) || [],
    },
    elementType:
        props.value?.type === 'array'
            ? props.value.elementType
            : {
                  type: undefined,
              },
});

const showDouble = computed(() => {
    return ['float', 'double'].includes(formData.value.type);
});

const showString = computed(() => {
    return ['string', 'password'].includes(formData.value.type);
});

const showBoolean = computed(() => {
    return formData.value.type === 'boolean';
});

const showDate = computed(() => {
    return formData.value.type === 'date';
});

const showEnum = computed(() => {
    return formData.value.type === 'enum';
});

const showArray = computed(() => {
    return formData.value.type === 'array';
});

const rules = [
    {
        validator(_, value) {
            if (!value) {
                return Promise.reject('请选择元素类型');
            }
            return Promise.resolve();
        },
        trigger: 'change',
    },
];

const typeChange = (e) => {
    if (['float', 'double'].includes(e)) {
        formData.value.scale = 2;
    }
};

const initValue = () => {
    formData.value.type = props.value?.type;
    formData.value.scale = props.value?.scale;
    formData.value.expands.maxLength =
        props.value?.maxLength || props.value?.expands?.maxLength;
    formData.value.boolean = {
        trueText: props.value?.trueText || '是',
        trueValue: props.value?.trueValue || 'true',
        falseText: props.value?.falseText || '否',
        falseValue: props.value?.falseValue || 'false',
    };
    formData.value.format = props.value?.format;
    formData.value.enum = {
        multiple: props.value?.multiple,
        elements: cloneDeep(props.value?.elements || []),
    };

    formData.value.elementType =
        props.value?.type === 'array'
            ? props.value.elementType
            : {
                  type: undefined,
              };
};

const handleValue = (type, data) => {
    let newObject = {};
    switch (type) {
        case 'float':
        case 'double':
            newObject = pick(data, 'scale');
            break;
        case 'boolean':
            newObject = { ...data.boolean };
            break;
        case 'enum':
            newObject.elements = data.enum.elements;
            break;
        case 'string':
        case 'password':
            newObject = pick(data, 'expands');
            break;
        case 'date':
            newObject = pick(data, 'format');
            break;
        case 'array':
            newObject = pick(data, 'elementType');
    }

    return {
        type: type,
        ...newObject,
    };
};

const onOk = async () => {
    const data = await formRef.value.validate();
    let enumTable = true;
    if (enumTableRef.value) {
        enumTable = !!(await enumTableRef.value.validate());
    }
    if (data && enumTable) {
        visible.value = false;
        const _value = handleValue(formData.value.type, formData.value);
        emit('update:value', _value);
        emit('confirm', _value);
        formItemContext.onFieldChange();
    }
};

const onCancel = () => {
    formRef.value?.resetFields();
    initValue();
    emit('cancel');
};

const TypeChange = (extra) => {
    if (JSON.stringify(extra) !== '{}') {
        formData.value.boolean = {
            ...extra,
        };
    }
};

watch(
    () => JSON.stringify(props.value),
    () => {
        initValue();
    },
);
</script>

<style scoped></style>
